home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-01-31 | 12.8 KB | 401 lines | [TEXT/R*ch] |
- // ===========================================================================
- // File: UMenuedWindows.cp
- // Version: 1.0 - May 7, 1996
- // Author: Mike Shields (mshields@inconnect.com)
- //
- // Copyright ©1996 Mike Shields. All rights reserved.
- // I hereby grant users of UMenuedWindows permission to use it (or any modified
- // version of it) in applications (or any other type of Macintosh software
- // like extensions -- freeware, shareware, commercial, or other) for free,
- // subject to the terms that:
- //
- // (1) This agreement is non-exclusive.
- //
- // (2) I, Mike Shields, retain the copyright to the original source code.
- //
- // These two items are the only required conditions for use. However, I do have
- // an additional request. Note, however, that this is only a request, and
- // that it is not a required condition for use of this code.
- //
- // (1) That I be given credit for UMenuedWindows code in the copyrights or
- // acknowledgements section of your manual or other appropriate documentation.
- //
- //
- // I would like to repeat that this last item is only a request. You are prefectly
- // free to choose not to do any or all of them.
- //
- // This source code is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- // ===========================================================================
- // UMenuedWindows.h <- double-click + Command-D to see class declaration
- //
- // A set of classes which allow you to manage the dynamic portion of a Windows
- // menu in your application. These include the static class which does all of the
- // real work, an LAttachment class which manages the selection and hiliting of the
- // menu items, and a LWindow subclass which knows how to add and delete itself from
- // the menu
-
- #include "UMenuedWindows.h"
-
- #include <LWindow.h>
- #include <UWindows.h>
- #include <LMenu.h>
- #include <LMenuBar.h>
- #include <PP_Messages.h>
- #include <LString.h>
- #include <PP_KeyCodes.h>
- #include <UDesktop.h>
- #include <LArray.h>
-
- #ifndef __MENUS__
- #include <Menus.h>
- #endif
-
- ResIDT UMenuedWindows::sMenuID = 0;
- Int16 UMenuedWindows::sSeparatorPosition = 0;
- LArray* UMenuedWindows::sWindowList = nil;
-
- #pragma mark === UMenuedWindows ===
- //---------------------------------------------------------------------------
- // UMenuedWindows::InitMenuedWindows
- //---------------------------------------------------------------------------
- void UMenuedWindows::InitMenuedWindows(Int16 inMENUid, LApplication* inApplication)
- {
- SignalIf_(inApplication == nil);
-
- sMenuID = inMENUid;
-
- LMenu* theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(sMenuID);
- SignalIf_(theMenu == nil);
- sSeparatorPosition = ::CountMItems(theMenu->GetMacMenuH()) + 1;
- if ( sSeparatorPosition == 1 )
- sSeparatorPosition = 0;
- sWindowList = new LArray(sizeof(LWindow*));
-
- inApplication->AddAttachment(new CMenuedWindowsAttachment(sMenuID, sSeparatorPosition + 1));
- }
-
- //---------------------------------------------------------------------------
- // UMenuedWindows::AddWindowToMenu
- //---------------------------------------------------------------------------
- void UMenuedWindows::AddWindowToMenu(LWindow* inWindow)
- {
- SignalIf_(sWindowList == nil);
-
- LMenu* theMenu;
- MenuHandle macMenuH;
- Int16 menuLength;
- LStr255 windowTitle;
-
- theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(sMenuID);
- SignalIfNot_(theMenu);
-
- macMenuH = theMenu->GetMacMenuH();
- menuLength = ::CountMItems(macMenuH);
-
- // Insert separator line if neccessary
- if ( (sSeparatorPosition > 0) && ((menuLength + 1) == sSeparatorPosition) )
- {
- ::InsertMenuItem(macMenuH, "\p-", ++menuLength);
- }
-
- inWindow->GetDescriptor(windowTitle);
- ::InsertMenuItem(macMenuH, "\p ", ++menuLength);
- ::SetMenuItemText(macMenuH, menuLength, windowTitle);
-
- sWindowList->InsertItemsAt(1, LArray::index_Last, &inWindow);
-
- LCommander::SetUpdateCommandStatus(true);
- }
-
- //---------------------------------------------------------------------------
- // UMenuedWindows::RemoveWindowFromMenu
- //---------------------------------------------------------------------------
- void UMenuedWindows::RemoveWindowFromMenu(LWindow* inWindow)
- {
- SignalIf_(sWindowList == nil);
-
- LMenu* theMenu;
- MenuHandle macMenuH;
- Int16 menuLength;
- Int16 menuIndex;
-
- theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(sMenuID);
- SignalIfNot_(theMenu);
-
- macMenuH = theMenu->GetMacMenuH();
- menuLength = ::CountMItems(macMenuH);
-
- menuIndex = UMenuedWindows::WindowToMenuItem(inWindow);
-
- if ( menuIndex != LArray::index_Bad )
- {
- sWindowList->Remove(&inWindow);
-
- ::DeleteMenuItem(macMenuH, menuIndex);
- menuLength--;
-
- // Remove separator line if neccessary
- if ( (sSeparatorPosition > 1) && (menuLength == sSeparatorPosition) )
- ::DeleteMenuItem(macMenuH, menuLength);
-
- LCommander::SetUpdateCommandStatus(true);
- }
- }
-
- //---------------------------------------------------------------------------
- // UMenuedWindows::WindowToMenuItem
- //---------------------------------------------------------------------------
- Int16 UMenuedWindows::WindowToMenuItem(LWindow* inWindow)
- {
- SignalIf_(sWindowList == nil);
-
- Int16 result = LArray::index_Bad;
- ArrayIndexT windowIndex;
-
- if ( inWindow != NULL )
- {
- windowIndex = sWindowList->FetchIndexOf(&inWindow);
- if ( windowIndex != LArray::index_Bad )
- result = windowIndex + sSeparatorPosition;
- else
- SignalPStr_("\pInvalid LWindow to UMenuedWindows::WindowToMenuItem");
- }
- return result;
- }
-
- //---------------------------------------------------------------------------
- // UMenuedWindows::MenuItemToWindow
- //---------------------------------------------------------------------------
- LWindow* UMenuedWindows::MenuItemToWindow(Int16 inMenuItem)
- {
- SignalIf_(sWindowList == nil);
-
- LWindow* result = nil;
- Int16 listIndex = 1;
-
- if ( sSeparatorPosition > 0 && (inMenuItem > sSeparatorPosition) )
- listIndex = inMenuItem - sSeparatorPosition;
- else
- listIndex = inMenuItem;
-
- if ( sWindowList->FetchItemAt(listIndex, &result) == false )
- SignalPStr_("\pInvalid menu item to UMenuedWindows::MenuItemToWindow");
- return result;
- }
-
- //---------------------------------------------------------------------------
- // UMenuedWindows::SetCommandKey
- //---------------------------------------------------------------------------
- void UMenuedWindows::SetCommandKey(LWindow* inWindow, char inKey)
- {
- SignalIf_(sWindowList == nil);
-
- Int16 itsMenuItem;
-
- itsMenuItem = WindowToMenuItem(inWindow);
- if ( itsMenuItem != LArray::index_Bad )
- {
- LMenu* theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(sMenuID);
- SignalIfNot_(theMenu);
-
- ::SetItemCmd(theMenu->GetMacMenuH(), itsMenuItem, inKey);
- }
- }
-
- //---------------------------------------------------------------------------
- // UMenuedWindows::GetMenuItemStatus
- //---------------------------------------------------------------------------
- void UMenuedWindows::GetMenuItemStatus(Int16 inMenuItem, Boolean &outEnabled,
- Boolean &outUsesMark, Char16 &outMark,
- StringPtr outName)
- {
- SignalIf_(sWindowList == nil);
-
- // Set up some appropriate defaults in case something below goes wrong.
- outUsesMark = true,
- outMark = noMark;
-
- LWindow* theWindow = MenuItemToWindow(inMenuItem);
- if ( theWindow )
- {
- outEnabled = true;
-
- // if this is the top window, we want to show a check mark next to it.
- if ( UDesktop::FetchTopRegular() == theWindow )
- outMark = char_Lozenge;
-
- // We also want to update the title of the menu item to reflect
- // the current name.
- LStr255 windowTitle;
- theWindow->GetDescriptor(windowTitle);
-
- LString::CopyPStr(windowTitle, outName);
- }
- else
- {
- SignalPStr_("\pUMenuedWindows::GetMenuItemStatus: Window doesn't exist");
- }
- }
-
- //---------------------------------------------------------------------------
- // UMenuedWindows::SelectWindowMenuWindow
- //---------------------------------------------------------------------------
- void UMenuedWindows::SelectWindowMenuWindow(Int16 inMenuItem)
- {
- SignalIf_(sWindowList == nil);
-
- LWindow* theWindow = MenuItemToWindow(inMenuItem);
- if ( theWindow )
- {
- // Bring the window to the front and make sure it's visible.
- theWindow->Select();
- theWindow->Show();
- }
- else
- {
- SignalPStr_("\pUMenuedWindows::SelectWindowMenuWindow: Window doesn't exist");
- }
- }
-
- #pragma mark === CMenuedWindowsAttachment ===
- //---------------------------------------------------------------------------
- // CMenuedWindowsAttachment::CMenuedWindowsAttachment
- //---------------------------------------------------------------------------
- CMenuedWindowsAttachment::CMenuedWindowsAttachment(ResIDT inMenuID, Int16 inFirstItem)
- : LAttachment(msg_AnyMessage), mMenuID(inMenuID), mFirstItem(inFirstItem)
- {
- }
-
- //---------------------------------------------------------------------------
- // CMenuedWindowsAttachment::~CMenuedWindowsAttachment
- //---------------------------------------------------------------------------
- CMenuedWindowsAttachment::~CMenuedWindowsAttachment()
- {
- }
-
- //---------------------------------------------------------------------------
- // CMenuedWindowsAttachment::ExecuteSelf
- //---------------------------------------------------------------------------
- void CMenuedWindowsAttachment::ExecuteSelf(MessageT inMessage, void *ioParam)
- {
- ResIDT menuID;
- Int16 menuItem;
-
- // By default we want the host to execute.
- SetExecuteHost(true);
-
- if ( inMessage == msg_CommandStatus )
- {
- if ( UDesktop::FrontWindowIsModal() )
- {
- return;
- }
-
- SCommandStatus* status = (SCommandStatus*)ioParam;
- if ( LCommander::IsSyntheticCommand(status->command, menuID, menuItem) )
- {
- if ( menuID == mMenuID )
- {
- LMenu* theMenu;
- MenuHandle macMenuH;
- Int16 menuLength;
- Boolean usesMark;
- Char16 mark;
- Str255 name;
-
- theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(mMenuID);
- SignalIfNot_(theMenu);
- macMenuH = theMenu->GetMacMenuH();
- menuLength = ::CountMItems(macMenuH);
-
- for ( Int16 i = mFirstItem; i <= menuLength; i++ )
- {
- UMenuedWindows::GetMenuItemStatus(i, *status->enabled,
- usesMark, mark, name);
-
- if ( usesMark )
- ::SetItemMark(macMenuH, i, mark);
-
- if ( name[0] > 0 )
- ::SetMenuItemText(macMenuH, i, name);
- }
- // OK, we handled this so no reason for the host to try to handle it.
- SetExecuteHost(false);
- }
- }
- }
- else if ( LCommander::IsSyntheticCommand(inMessage, menuID, menuItem) )
- {
- // we're being asked to respond to selecting a command. If it's in the range of our menu
- // items we need to select the window.
- if ( menuID == mMenuID && menuItem >= mFirstItem )
- {
- UMenuedWindows::SelectWindowMenuWindow(menuItem);
-
- // OK, we handled this so no reason for the host to try to handle it.
- SetExecuteHost(false);
- }
- }
- }
-
- #pragma mark === CMenuedWindow ===
- //---------------------------------------------------------------------------
- // CMenuedWindow::CreateWindowStream
- //---------------------------------------------------------------------------
- // Return a newly created Window object initialized with data from a Stream
- CMenuedWindow* CMenuedWindow::CreateFromStream(LStream *inStream)
- {
- return (new CMenuedWindow(inStream));
- }
-
- //---------------------------------------------------------------------------
- // CMenuedWindow::CMenuedWindow
- //---------------------------------------------------------------------------
- // Default Constructor
- CMenuedWindow::CMenuedWindow()
- {
- }
-
- //---------------------------------------------------------------------------
- // CMenuedWindow::CMenuedWindow(SWindowInfo&)
- //---------------------------------------------------------------------------
- // Construct Window from the data in a struct
- CMenuedWindow::CMenuedWindow(const SWindowInfo &inWindowInfo)
- : LWindow(inWindowInfo)
- {
- UMenuedWindows::AddWindowToMenu(this);
- }
-
- //---------------------------------------------------------------------------
- // CMenuedWindow::CMenuedWindow(ResIDT, Uint32, LCommander*)
- //---------------------------------------------------------------------------
- // Construct a Window from a WIND Resource with the specified attributes
- // and SuperCommander
- CMenuedWindow::CMenuedWindow(ResIDT inWINDid, Uint32 inAttributes, LCommander *inSuper)
- : LWindow(inWINDid, inAttributes, inSuper)
- {
- UMenuedWindows::AddWindowToMenu(this);
- }
-
- //---------------------------------------------------------------------------
- // CMenuedWindow::CMenuedWindow(LStream*)
- //---------------------------------------------------------------------------
- // Construct Window from the data in a stream
- CMenuedWindow::CMenuedWindow(LStream *inStream)
- : LWindow(inStream)
- {
- UMenuedWindows::AddWindowToMenu(this);
- }
-
- //---------------------------------------------------------------------------
- // CMenuedWindow::~CMenuedWindow
- //---------------------------------------------------------------------------
- // Destructor
- CMenuedWindow::~CMenuedWindow()
- {
- UMenuedWindows::RemoveWindowFromMenu(this);
- }
-
-